<template>
  <t-modal
    title="导入压缩包"
    :width="fileParsing ? '1480px' : '700px'"
    :visible="visible"
    :footer="null"
    @cancel="closeModal()"
    wrapClassName="upload-drawing-container"
    forceRender
  >
    <div class="spin-container" v-if="fileParseLoading">
      <a-spin tip="正在解析压缩包文件..."> </a-spin>
    </div>
    <div class="modal-body-container">
      <!-- 文件列表 -->
      <div class="view-zip-container" v-if="fileParsing">
        <div class="folder-tree-container">
          <div class="tree-container">
            <a-empty v-if="treeData.length == 0" :description="false" />
            <a-tree
              v-else
              v-model="checkedKeys"
              show-icon
              show-line
              :expanded-keys="expandedKeys"
              :auto-expand-parent="autoExpandParent"
              :selected-keys="selectedKeys"
              :tree-data="treeData"
              :replaceFields="{
                children: 'children',
                title: 'nodeName',
                key: 'uuid',
              }"
              @expand="onExpand"
              @select="onSelect"
            >
              <!-- 自定义图标 -->
              <template slot="custom">
                <icon-font type="icon-wenjianjia-" />
              </template>
              <template slot="title" slot-scope="{ nodeName }">
                <div class="custom-tree-title-warp">
                  <div class="title" :title="nodeName">
                    {{ nodeName }}
                  </div>
                </div>
              </template>
            </a-tree>
          </div>
        </div>
        <!--  -->
        <div class="folder-file-list">
          <vxe-table
            ref="xTable"
            height="100%"
            align="center"
            show-overflow
            show-header-overflow
            border="inner"
            :data="tableData"
            :column-config="{ resizable: true }"
          >
            <vxe-column type="seq" width="80" title="序号"></vxe-column>
            <vxe-column field="nodeName" title="文件名称">
              <template #default="{ row }">
                {{ row.nodeName }}.{{ row.type }}
              </template>
            </vxe-column>
            <vxe-column field="nickname" title="上传人"> </vxe-column>
            <vxe-column field="date" title="上传时间"> </vxe-column>
            <vxe-column field="operate" width="90" title="操作" fixed="right">
              <template #default="{ row }">
                <div class="text-button-group">
                  <a-icon
                    :type="getIcon(row)"
                    :style="{ color: getIconColor(row) }"
                    @click="deleteFile(row)"
                  />
                </div>
              </template>
            </vxe-column>
          </vxe-table>
        </div>
      </div>
      <!-- 选择压缩包 -->
      <div class="upload-dragger-container" v-else>
        <a-upload-dragger
          v-if="!fileParseLoading"
          name="file"
          :multiple="false"
          accept=".zip"
          :beforeUpload="beforeUpload"
          :fileList="fileList"
        >
          <p class="ant-upload-drag-icon">
            <a-icon type="inbox" />
          </p>
          <p class="ant-upload-text">
            单击或拖动文件到此区域进行上传
          </p>
          <p style="color:red">仅支持.zip格式文件</p>
        </a-upload-dragger>
      </div>
    </div>

    <!-- footer -->
    <div class="modal-footer" v-if="fileParsing">
      <a-button class="cu-btn-filter" @click="closeModal()">
        取消
      </a-button>
      <a-button
        class="cu-btn-primary"
        :disabled="zipFileList.length == 0"
        @click="handleOk()"
        :loading="confirmLoading"
      >
        确定
      </a-button>
    </div>
  </t-modal>
</template>

<script>
import {
  randomUUID,
  flatTreeData,
  addAttributeByKey,
  getNowDateStr,
  deleteNodeByKey,
  getNodeByKey,
} from "@/utils/util";
import cloneDeep from "lodash.clonedeep";
import { Icon } from "ant-design-vue";
import iconfrontjs from "@/assets/IconFont/iconfont.js";
const iconFrontUrl = iconfrontjs;
const IconFont = Icon.createFromIconfontCN({
  scriptUrl: iconFrontUrl,
});
import JSZip from "jszip";
import { mapGetters } from "vuex";
import { axios } from "@/utils/request";
import { Number } from "core-js";
export default {
  inject: ["moduleSource"],
  components: {
    IconFont,
  },
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    treeItem: {
      type: Object,
      default: () => {
        return {};
      },
    },
    //文件格式： ['dwg', 'dxf']
    accept: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      //确定按钮loading
      confirmLoading: false,
      fileList: [],
      fileParsing: false,
      fileParseLoading: false,
      expandedKeys: [],
      autoExpandParent: true,
      checkedKeys: [],
      selectedKeys: [],
      treeData: [],
      currentTreeNode: [],
      tableData: [],
      cloneTreeData: [],
      zipInstance: null,
      zipFileList: [],
    };
  },
  watch: {
    visible: {
      handler(val) {
        if (val) {
          console.log();
        }
      },
    },
  },
  computed: {
    ...mapGetters(["nickname"]),
  },
  methods: {
    //确定
    async handleOk() {
      let { zipFileList, cloneTreeData, tableData, accept } = this;
      try {
        let otherAcceptFiles = zipFileList.filter(
          (v) => !accept.includes(v.fileType)
        );
        if (accept.length > 0 && otherAcceptFiles.length > 0) {
          this.$message.error(`仅支持上传【${accept.toString()}】格式的文件!`);
          return;
        }
        console.log(zipFileList, accept, otherAcceptFiles);
        this.confirmLoading = true;
        tableData.forEach((v) => {
          v.status = 1;
        });
        const uploadFilePromises = zipFileList.map((item) => {
          return this.handleUploadFile(item);
        });
        await Promise.all(uploadFilePromises).finally((_) => {
          zipFileList.forEach((v) => {
            let { id, dfsFileUuid } = v;
            let itemNode = getNodeByKey(id, "uuid", cloneTreeData, "children");
            if (itemNode) {
              itemNode.dfsFileUuid = dfsFileUuid;
            }
          });
          this.saveZipData().then((res) => {
            let { addClassifyIdLs, addFileIdLs, fileInfo } = res;
            this.confirmLoading = false;
            this.$emit("change", {
              treeData: cloneTreeData,
              fileList: zipFileList,
              addClassifyIdLs,
              addFileIdLs,
              fileInfo,
            });
            this.closeModal();
          });
        });
      } catch (error) {}
    },

    //上传文件
    handleUploadFile(fileObj = {}) {
      return new Promise(async (resolve, reject) => {
        let { file, id } = fileObj;
        let { tableData, cloneTreeData } = this;
        let { name } = file;

        let flatData = flatTreeData(cloneTreeData, "children");
        let arrayFiles = (flatData || []).filter((v) => v.type != "folder");
        let itemRow = arrayFiles.find((v) => v.uuid == id);

        const lastDotIndex = name.lastIndexOf("/");
        let fileName = name.substring(lastDotIndex + 1);
        const fileData = await file.async("arraybuffer");
        if (fileData.byteLength > 0) {
          let formData = new FormData();
          formData.append("bucket", "yx-cloud-vue");
          formData.append("file", new Blob([fileData]), fileName);
          axios
            .post(`/document/minio/uploadfileOnlyTable`, formData, {
              headers: {
                "Content-Type": "multipart/form-data",
              },
            })
            .then((res) => {
              let { statusCode } = res;
              if (statusCode == 200) {
                let { dfsFileUuid } = res;
                fileObj.dfsFileUuid = dfsFileUuid;
                this.$set(itemRow, "status", 2);
                resolve();
              } else {
                fileObj.dfsFileUuid = -1;
                this.$set(itemRow, "status", 3);
                // this.$message.error(
                //   `文件【${fileName}】上传失败，请稍后重试！`
                // );
                resolve();
              }
            })
            .catch((_) => {
              fileObj.dfsFileUuid = -1;
              this.$set(itemRow, "status", 3);
              //   this.$message.error(`文件【${fileName}】上传失败，请稍后重试！`);
              resolve();
            })
            .finally((_) => {});
        } else {
          fileObj.dfsFileUuid = -1;
          this.$set(itemRow, "status", 3);
          resolve();
        }
      });
    },

    //保存压缩包
    saveZipData() {
      let { treeItem, cloneTreeData } = this;
      return new Promise((resolve, reject) => {
        axios
          .post(
            `/probusiness/bimCadClassify/saveZipDataOther`,
            {
              type: this.moduleSource(),
              pid: treeItem.id,
              zipData: cloneTreeData,
            },
            {
              headers: {
                "Content-Type": "application/json",
              },
            }
          )
          .then((res) => {
            let { statusCode, data } = res;
            if (statusCode == 200) {
              resolve(data);
            } else {
              resolve({});
            }
          })
          .catch((_) => {
            resolve({});
          })
          .finally((_) => {});
      });
    },

    //删除文件
    deleteFile(row = {}) {
      let { uuid } = row;
      let { cloneTreeData, zipFileList } = this;
      this.tableData = this.tableData.filter((v) => v.uuid != uuid);
      this.zipFileList = zipFileList.filter((v) => v.id != uuid);
      let newData = deleteNodeByKey(uuid, "uuid", cloneTreeData, "children");
      this.cloneTreeData = newData?.treeData || [];
    },

    //监听树形选择
    onSelect(selectedKeys, info) {
      let { uuid } = info.node.dataRef;
      this.currentTreeNode = info.node.dataRef;
      this.selectedKeys = [uuid];
      this.tableData = this.getFileList(uuid);
    },

    onExpand(expandedKeys) {
      this.expandedKeys = expandedKeys;
      this.autoExpandParent = false;
    },

    //上传文件前置监听
    beforeUpload(file, fileList) {
      if (file) {
        this.fileParseLoading = true;
        this.handleFileUpload(file);
      }
      this.fileList = fileList;
      return false;
    },

    //解析压缩包
    async handleFileUpload(file) {
      if (file) {
        try {
          this.zipInstance = new JSZip();
          const contents = await this.zipInstance.loadAsync(file);
          //重构压缩包数据
          this.parseZipContents(contents);
          this.fileParseLoading = false;
          this.fileParsing = true;
        } catch (error) {
          let { name } = file;
          this.fileParsing = false;
          this.$message.error(`【${name}】解析失败：` + error);
        }
      }
    },

    //重构压缩包数据
    parseZipContents(contents) {
      const structure = [];
      contents.forEach(async (relativePath, file) => {
        const parts = relativePath.split("/").filter((part) => part !== "");
        let currentLevel = structure;
        parts.forEach(async (part, index) => {
          let nodeName,
            type,
            uuid,
            date,
            nickname,
            name,
            status,
            id,
            scopedSlots,
            $$dataType;
          if (index === parts.length - 1 && !file.dir) {
            // 这是一个文件
            const lastDotIndex = part.lastIndexOf(".");
            if (lastDotIndex !== -1) {
              let uid = randomUUID();
              nodeName = part.substring(0, lastDotIndex);
              name = part.substring(0, lastDotIndex);
              type = part.substring(lastDotIndex + 1);
              uuid = uid;
              id = uid;
              date = getNowDateStr(1);
              nickname = this.nickname;
              status = 0;
              $$dataType = 1;
              scopedSlots = { icon: "custom" };
              this.zipFileList.push({ file, id: uid, fileType: type });
            } else {
              let uid = randomUUID();
              uuid = uid;
              id = uid;
              nodeName = part;
              name = part;
              type = "";
              date = getNowDateStr(1);
              nickname = this.nickname;
              status = 0;
              scopedSlots = { icon: "custom" };
              $$dataType = 1;
              this.zipFileList.push({ file, id: uid, fileType: type });
            }
          } else {
            // 这是一个文件夹
            let uid = randomUUID();
            nodeName = part;
            name = part;
            type = "folder";
            uuid = uid;
            id = uid;
            date = getNowDateStr(1);
            nickname = this.nickname;
            scopedSlots = { icon: "custom" };
            status = 0;
            $$dataType = 1;
          }
          let existingItem = currentLevel.find(
            (item) => item.nodeName === nodeName
          );
          if (!existingItem) {
            const newItem = {
              nodeName,
              name,
              type,
              uuid,
              id,
              date,
              nickname,
              status,
              scopedSlots,
              $$dataType,
              children: [],
            };
            currentLevel.push(newItem);
            existingItem = newItem;
          }
          if (existingItem.children) {
            currentLevel = existingItem.children || [];
          }
        });
        //
      });

      //copy原始数据
      this.cloneTreeData = cloneDeep(structure);
      //重构树形数据
      let filterData = addAttributeByKey(
        null,
        "scopedSlots",
        { icon: "custom" },
        structure,
        "children"
      );
      this.treeData = this.getFolderData(filterData);
      this.$nextTick((_) => {
        let firstNode = filterData?.[0] ?? {};
        this.currentTreeNode = firstNode;
        this.selectedKeys = [firstNode?.uuid];
        this.tableData = this.getFileList(firstNode?.uuid);
        //展开所有目录
        this.expandedKeys = flatTreeData(filterData, "children").map(
          (v) => v.uuid
        );
      });
    },

    //过滤出所有文件夹数据
    getFolderData(data) {
      try {
        filterData(data);
        function filterData(source = []) {
          source.forEach((item) => {
            if (item.type === "folder") {
              if (item.children && item.children.length) {
                item.children = item.children.filter(
                  (v) => v.type === "folder"
                );
                filterData(item.children);
              }
            }
          });
        }
        throw data;
      } catch (data) {
        return data;
      }
    },

    //获取文件夹下面的文件列表
    getFileList(uuid) {
      let { cloneTreeData } = this;
      let flatData = flatTreeData(cloneTreeData, "children");
      let itemNode = flatData.find((v) => v.uuid == uuid);
      let flatChildData = flatTreeData([itemNode], "children");
      let fileList = (flatChildData || []).filter((v) => v.type != "folder");
      return fileList;
    },

    //关闭弹窗
    closeModal() {
      this.$emit("update:visible", false);
      setTimeout((_) => {
        this.confirmLoading = false;
        this.fileParsing = false;
        this.fileList = [];
        this.zipFileList = [];
        this.cloneTreeData = [];
        this.fileParseLoading = false;
      }, 500);
    },

    //设置图片
    getIcon(row = {}) {
      let { status } = row;
      switch (Number(status)) {
        //初始化
        case 0:
          return "close";

        //上传中
        case 1:
          return "loading";

        //上传成功
        case 2:
          return "check-circle";

        //上传失败
        case 3:
          return "exclamation-circle";

        default:
          break;
      }
    },

    //设置图表样式
    getIconColor(row = {}) {
      let { status } = row;
      switch (Number(status)) {
        //初始化
        case 0:
          return "#FF2D2D";

        //上传中
        case 1:
          return "#1890ff";

        //上传成功
        case 2:
          return "#52c41a";

        //上传失败
        case 3:
          return "#FF2D2D";

        default:
          break;
      }
    },
  },
};
</script>

<style lang="less" scoped>
/deep/.upload-drawing-container {
  .ant-modal-body {
    padding: 0 !important;
    position: relative;
    .modal-body-container {
      padding: 24px 30px;
    }
    .modal-footer {
      display: flex;
      height: 54px;
      align-items: center;
      justify-content: flex-end;
      padding: 0 6px;
      border-top: 1px solid #e8e8e8;
      button {
        margin-left: 8px;
      }
    }
    .spin-container {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 99;
    }
    //文件列表
    .view-zip-container {
      height: 562px;
      display: flex;
      overflow: hidden;
      .folder-tree-container {
        flex-shrink: 0;
        height: 100%;
        width: 300px;
        border: 1px solid #d4d7d8;
        border-radius: 4px;
        overflow: hidden;
        .tree-container {
          height: 100%;
          flex: 1;
          overflow: auto;
          overflow-x: hidden;
          position: relative;
          padding: 0 10px 0 14px;
          .ant-tree {
            li {
              width: 100%;
              .ant-tree-node-content-wrapper {
                position: relative;
                width: calc(100% - 25px);
                padding: 0;
                .ant-tree-iconEle {
                  color: #f3ab1f;
                  font-size: 16px;
                }

                .ant-tree-title {
                  overflow: hidden;
                  display: inline-block;
                  width: calc(100% - 26px);
                  .custom-tree-title-warp {
                    display: flex;
                    width: 100%;
                    .title {
                      flex: 1;
                      overflow: hidden;
                      overflow: hidden;
                      white-space: nowrap;
                      text-overflow: ellipsis;
                    }
                  }
                }
              }
            }
          }
          .ant-empty {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
          }
        }
      }
      .folder-file-list {
        margin-left: 10px;
        flex: 1;
        height: 100%;
        border: 1px solid #d4d7d8;
        border-radius: 4px;
        overflow: hidden;
      }
    }
    .upload-dragger-container {
      height: 240px;
    }
    .ant-upload-drag {
    }
    .ant-upload-list {
      display: none;
    }
  }
}
</style>
